import { JavascriptGenerator, javascriptGenerator } from "blockly/javascript";
import { Tanslate } from "./translate";
import * as Blockly from 'blockly/core';
export namespace Funcs {
    const blocks = [
        {
            "key": "func_args",
            "message0": "%{func_args} %1",
            "args0": [
                {
                    "type": "field_number",
                    "name": "index",
                    "value": 0,
                    "min": 0,
                    "max": 100,
                    "precision": 1
                },
            ],
            "output": null,
            "tooltip": "%{func_args_tips}",
            "colour": 260
        },
        {
            "key": "async_func",
            "message0": "%{async_func} %1 %{func_is_async} %2 %{func_is_global} %3 %{func_args_length} %4",
            "args0": [
                {
                    "type": "field_input",
                    "name": "name",
                    "text": "my_func",
                    "spellcheck": (val: string) => val.replace(/[^a-zA-Z0-9_]/g, '')
                },
                {
                    "type": "field_checkbox",
                    "name": "isAsync",
                    "checked": true
                },
                {
                    "type": "field_checkbox",
                    "name": "global",
                    "checked": false
                },
                {
                    "type": "field_number",
                    "name": "args",
                    "value": 0,
                    "min": 0,
                    "max": 100,
                    "precision": 1
                },
            ],
            "message1": "%{func_body} %1",
            "args1": [
                {
                    'type': 'input_statement',
                    'name': 'body0',
                },
            ],
            "nextStatement": null,
            "previousStatement": null,
            "colour": 260
        },
        {
            "key": "func_return",
            "message0": "%{func_return} %1",
            "args0": [
                {
                    "type": "input_value",
                    "name": "args"
                },
            ],
            "nextStatement": null,
            "previousStatement": null,
            "colour": 260
        },
        {
            "key": "func_await",
            "message0": "%{func_await} %1",
            "args0": [
                {
                    "type": "input_value",
                    "name": "func",
                    "check": ["func_call", "Promise"]
                },
            ],
            "output": null,
            "nextStatement": null,
            "previousStatement": null,
            "colour": 260
        },
        {
            "key": "func_call",
            "message0": "%{func_call} %1 %{func_args} %2",
            "args0": [
                {
                    "type": "input_value",
                    "name": "func",
                    "check": "String"
                },
                {
                    "type": "input_value",
                    "name": "args",
                    "check": "Array"
                },
            ],
            "output": null,
            "nextStatement": null,
            "previousStatement": null,
            "inputsInline": true,
            "tooltip": "%{call_func_tips}",
            "colour": 260
        }
    ]

    export function init() {
        initGenerator()
        Tanslate.tr(blocks).forEach((item: any) => {
            Blockly.Blocks[item.key] = {
                init: function (this: any) {
                    this.jsonInit(item);
                }
            }
        })
    }

    export function getTools() {
        const netBlocks = {
            kind: 'category',
            name: Blockly.Msg['procedures'],
            "colour": 260,
            contents: [] as any[]
        }
        blocks.forEach((item: any) => {
            netBlocks.contents.push({
                kind: 'block',
                type: item.key
            })
        })

        return netBlocks
    }

    function getValue(block: Blockly.Block, generator: JavascriptGenerator, name: string) {
        let val: string | undefined = undefined
        try {
            val = generator.statementToCode(block, name).trim();
        } catch (error) {
            try {
                val = generator.valueToCode(block, name, 0);
            } catch (error) {
                val = undefined
            }
        }
        return val
    }

    function initGenerator() {
        javascriptGenerator.forBlock['func_args'] = function (block: Blockly.Block) {
            const index = block.getFieldValue('index');
            return `args_${index}`;
        }
        javascriptGenerator.forBlock['func_return'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const args = getValue(block, generator, 'args')?.trim();
            if (args) {
                return `return ${args};\n`;
            }
            return `return;\n`;
        }
        javascriptGenerator.forBlock['async_func'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const name = block.getFieldValue('name');
            const isAsync = block.getFieldValue('isAsync');
            const isGlobal = block.getFieldValue('global');
            const args = block.getFieldValue('args');
            const body = block.getInputTargetBlock('body0');
            let lines = ''
            if (body) {
                const line = generator.blockToCode(body)
                lines = (typeof line === 'string' ? line : line.join('\n'))
            }
            const argsAr: string[] = []
            for (let i = 0; i < args; i++) {
                argsAr.push(`args_${i}`)
            }
            if (!name) {
                throw new Error(block.id);
            }
            if (isGlobal === 'TRUE') {
                return `Dog.GlobalMap['${name}'] = ${isAsync === 'TRUE' ? 'async ' : ''} (${argsAr.join(',')})=>{\n${lines}\n};\n`;
            }
            return `${isAsync === 'TRUE' ? 'async ' : ''} function ${name}(${argsAr.join(',')}){\n${lines}\n};\n`;
        }

        javascriptGenerator.forBlock['func_await'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const func = getValue(block, generator, 'func')?.trim();
            if (!func) {
                throw new Error(block.id);
            }
            return `await ${func}`;
        }

        javascriptGenerator.forBlock['func_call'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const func = getValue(block, generator, 'func')?.trim();
            const args = getValue(block, generator, 'args');
            if (!func) {
                throw new Error(block.id);
            }
            if(block.outputConnection?.targetBlock()) {
                return `${func.replace(/['"]/g, '')}(...${args || '[]'})`;
            }
            return `${func.replace(/['"]/g, '')}(...${args || '[]'});\n`;
        }
    }
}